package dpda;

import pda.PDAConfiguration;

import java.util.HashSet;
import java.util.Set;

/**
 * @author haoly
 * @title DPDA
 * @date 2025/4/21 11:08
 * @description TODO
 */
public class DPDA <T>{
    private PDAConfiguration<T> currentConfiguration;

    private final Set<T> acceptStates;

    private final DPDARulebook<T> rulebook;

    public DPDA(PDAConfiguration<T> currentConfiguration, Set<T> acceptStates, DPDARulebook<T> rulebook) {
        this.currentConfiguration = currentConfiguration;
        this.acceptStates = new HashSet<>(acceptStates);
        this.rulebook = rulebook;
    }

    public Boolean accetpting(){
        return this.currentConfiguration != null && acceptStates.contains(this.getCurrentConfiguration().getState());
    }

    public void readChracter(Character character){
//        PDAConfiguration<T> nextConfiguration = this.rulebook.nextConfiguration(this.currentConfiguration, character);
//        this.currentConfiguration = nextConfiguration;
//        if (this.currentConfiguration != null) {
//            this.currentConfiguration = this.rulebook.followFreeMoves(this.currentConfiguration);
//        }
        this.currentConfiguration = nextConfiguration(character);
    }

    private PDAConfiguration<T> nextConfiguration(Character character) {
        if (rulebook.appliesTo(getCurrentConfiguration(), character)) {
            return rulebook.nextConfiguration(getCurrentConfiguration(), character);
        }else {
            return currentConfiguration.stuck();
        }
    }

    public void readString(String s){
        for (int i = 0; i < s.length(); i++) {
            if (!isStuck()) {
                readChracter(s.charAt(i));
            }
        }
    }

    public Boolean isStuck(){
        return currentConfiguration.isStuck();
    }

    @Override
    public String toString() {
        return "#struct DPDA ...>";
    }

    public PDAConfiguration<T> getCurrentConfiguration() {
        return rulebook.followFreeMoves(currentConfiguration);
    }

    public Set<T> getAcceptStates() {
        return acceptStates;
    }

    public DPDARulebook<T> getRulebook() {
        return rulebook;
    }
}
